home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / totem / plugins / youtube / youtube.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  15.7 KB  |  392 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import totem
  5. import gobject
  6. import gtk
  7. import gconf
  8. gobject.threads_init()
  9. import gdata.service as gdata
  10. import urllib
  11. import httplib
  12. import atom
  13. import threading
  14. import time
  15. import re
  16. import os
  17. import random
  18.  
  19. class DownloadThread(threading.Thread):
  20.     
  21.     def __init__(self, youtube, url, treeview_name):
  22.         self.youtube = youtube
  23.         self.url = url
  24.         self.treeview_name = treeview_name
  25.         self._done = False
  26.         self._lock = threading.Lock()
  27.         threading.Thread.__init__(self)
  28.  
  29.     
  30.     def run(self):
  31.         
  32.         try:
  33.             res = self.youtube.service.Get(self.url).entry
  34.         except gdata.service.RequestError:
  35.             res = None
  36.  
  37.         gobject.idle_add(self.publish_results, res)
  38.  
  39.     
  40.     def publish_results(self, res):
  41.         self._lock.acquire(True)
  42.         self.youtube.entry[self.treeview_name] = res
  43.         self._done = True
  44.         self._lock.release()
  45.         return False
  46.  
  47.     
  48.     def done(self):
  49.         ''' Thread-safe property to know whether the query is done or not '''
  50.         self._lock.acquire(True)
  51.         res = self._done
  52.         self._lock.release()
  53.         return res
  54.  
  55.     done = property(done)
  56.  
  57.  
  58. class CallbackThread(threading.Thread):
  59.     
  60.     def __init__(self, callback, *args, **kwargs):
  61.         self.callback = callback
  62.         self.args = args
  63.         self.kwargs = kwargs
  64.         threading.Thread.__init__(self)
  65.  
  66.     
  67.     def run(self):
  68.         res = self.callback(*self.args, **self.kwargs)
  69.         while res == True:
  70.             res = self.callback(*self.args, **self.kwargs)
  71.  
  72.  
  73.  
  74. class YouTube(totem.Plugin):
  75.     
  76.     def __init__(self):
  77.         totem.Plugin.__init__(self)
  78.         self.debug = False
  79.         self.gstreamer_plugins_present = True
  80.         self.in_search = { }
  81.         self.search_token = { }
  82.         self.max_results = 20
  83.         self.button_down = False
  84.         self.search_terms = ''
  85.         self.youtube_id = ''
  86.         self.start_index = { }
  87.         self.results = { }
  88.         self.entry = { }
  89.         self.current_treeview_name = ''
  90.         self.notebook_pages = []
  91.         self.vadjust = { }
  92.         self.liststore = { }
  93.         self.treeview = { }
  94.  
  95.     
  96.     def activate(self, totem_object):
  97.         '''Check for the availability of the flvdemux and souphttpsrc GStreamer plugins'''
  98.         bvw_name = totem_object.get_video_widget_backend_name()
  99.         self.gconf_client = gconf.client_get_default()
  100.         if bvw_name.find('GStreamer') != -1:
  101.             
  102.             try:
  103.                 import pygst
  104.                 pygst.require('0.10')
  105.                 import gst
  106.                 registry = gst.registry_get_default()
  107.                 if registry.find_plugin('soup') == None:
  108.                     self.gstreamer_plugins_present = False
  109.             except ImportError:
  110.                 pass
  111.             except:
  112.                 None<EXCEPTION MATCH>ImportError
  113.             
  114.  
  115.         None<EXCEPTION MATCH>ImportError
  116.         self.builder = self.load_interface('youtube.ui', True, totem_object.get_main_window(), self)
  117.         self.totem = totem_object
  118.         self.search_entry = self.builder.get_object('yt_search_entry')
  119.         self.search_entry.connect('activate', self.on_search_entry_activated)
  120.         self.search_button = self.builder.get_object('yt_search_button')
  121.         self.search_button.connect('clicked', self.on_search_button_clicked)
  122.         self.progress_bar = self.builder.get_object('yt_progress_bar')
  123.         self.notebook = self.builder.get_object('yt_notebook')
  124.         self.notebook.connect('switch-page', self.on_notebook_page_changed)
  125.         self.notebook_pages = [
  126.             'search',
  127.             'related']
  128.         for page in self.notebook_pages:
  129.             self.setup_treeview(page)
  130.         
  131.         self.current_treeview_name = 'search'
  132.         self.vbox = self.builder.get_object('yt_vbox')
  133.         self.vbox.show_all()
  134.         totem_object.add_sidebar_page('youtube', _('YouTube'), self.vbox)
  135.         self.service = gdata.service.GDataService(account_type = 'HOSTED_OR_GOOGLE', server = 'gdata.youtube.com')
  136.  
  137.     
  138.     def deactivate(self, totem):
  139.         totem.remove_sidebar_page('youtube')
  140.  
  141.     
  142.     def setup_treeview(self, treeview_name):
  143.         self.start_index[treeview_name] = 1
  144.         self.results[treeview_name] = 0
  145.         self.entry[treeview_name] = None
  146.         self.in_search[treeview_name] = False
  147.         renderer = totem.CellRendererVideo(use_placeholder = True)
  148.         treeview = self.builder.get_object('yt_treeview_' + treeview_name)
  149.         treeview.set_property('totem', self.totem)
  150.         treeview.connect('row-activated', self.on_row_activated)
  151.         treeview.connect_after('starting-video', self.on_starting_video)
  152.         treeview.insert_column_with_attributes(0, _('Videos'), renderer, thumbnail = 0, title = 1)
  153.         ui_manager = treeview.get_ui_manager()
  154.         action_group = gtk.ActionGroup('youtube-action-group')
  155.         action = gtk.Action('open-in-web-browser', _('_Open in Web Browser'), _('Open the video in your web browser'), 'gtk-jump-to')
  156.         action_group.add_action_with_accel(action, None)
  157.         ui_manager.insert_action_group(action_group, 1)
  158.         ui_manager.add_ui(ui_manager.new_merge_id(), '/ui/totem-video-list-popup/', 'open-in-web-browser', 'open-in-web-browser', gtk.UI_MANAGER_MENUITEM, False)
  159.         menu_item = ui_manager.get_action('/ui/totem-video-list-popup/open-in-web-browser')
  160.         menu_item.connect('activate', self.on_open_in_web_browser_activated)
  161.         self.vadjust[treeview_name] = treeview.get_vadjustment()
  162.         self.vadjust[treeview_name].connect('value-changed', self.on_value_changed)
  163.         vscroll = self.builder.get_object('yt_scrolled_window_' + treeview_name).get_vscrollbar()
  164.         vscroll.connect('button-press-event', self.on_button_press_event)
  165.         vscroll.connect('button-release-event', self.on_button_release_event)
  166.         self.liststore[treeview_name] = self.builder.get_object('yt_liststore_' + treeview_name)
  167.         self.treeview[treeview_name] = treeview
  168.         treeview.set_model(self.liststore[treeview_name])
  169.  
  170.     
  171.     def on_notebook_page_changed(self, notebook, notebook_page, page_num):
  172.         self.current_treeview_name = self.notebook_pages[page_num]
  173.  
  174.     
  175.     def on_row_activated(self, treeview, path, column):
  176.         if self.debug:
  177.             print 'Activating row'
  178.         
  179.         (model, rows) = treeview.get_selection().get_selected_rows()
  180.         iter = model.get_iter(rows[0])
  181.         youtube_id = model.get_value(iter, 3)
  182.         self.youtube_id = youtube_id
  183.         self.start_index['related'] = 1
  184.         self.results['related'] = 0
  185.         if self.in_search == False or self.current_treeview_name == 'related':
  186.             self.progress_bar.set_text(_('Fetching related videos...'))
  187.         
  188.         self.get_results('/feeds/api/videos/' + urllib.quote(youtube_id) + '/related?max-results=' + str(self.max_results), 'related')
  189.         if self.debug:
  190.             print 'Done activating row'
  191.         
  192.  
  193.     
  194.     def get_fmt_string(self):
  195.         if self.gconf_client.get_int('/apps/totem/connection_speed') >= 10:
  196.             return '&fmt=18'
  197.         return ''
  198.  
  199.     
  200.     def resolve_t_param(self, youtube_id):
  201.         '''We have to get the t parameter from the actual video page, since Google changed how their URLs work'''
  202.         stream = urllib.urlopen('http://youtube.com/watch?v=' + urllib.quote(youtube_id))
  203.         regexp1 = re.compile('swfArgs.*"t": "([^"]+)"')
  204.         regexp2 = re.compile('</head>')
  205.         contents = stream.read()
  206.         stream.close()
  207.         return ''
  208.  
  209.     
  210.     def on_starting_video(self, treeview, path, user_data):
  211.         """Display an error if the required GStreamer plugins aren't installed"""
  212.         if self.gstreamer_plugins_present == False:
  213.             self.totem.interface_error_with_link(_('Totem cannot play this type of media (%s) because you do not have the appropriate plugins to handle it.') % _('YouTube'), _('Please install the necessary plugins and restart Totem to be able to play this media.'), 'http://www.gnome.org/projects/totem/#codecs', _('More information about media plugins'), self.totem.get_main_window())
  214.             return False
  215.         return True
  216.  
  217.     
  218.     def on_open_in_web_browser_activated(self, action):
  219.         (model, rows) = self.treeview[self.current_treeview_name].get_selection().get_selected_rows()
  220.         iter = model.get_iter(rows[0])
  221.         youtube_id = model.get_value(iter, 3)
  222.         os.spawnlp(os.P_NOWAIT, 'xdg-open', 'xdg-open', 'http://www.youtube.com/watch?v=' + urllib.quote(youtube_id) + self.get_fmt_string())
  223.  
  224.     
  225.     def on_button_press_event(self, widget, event):
  226.         self.button_down = True
  227.  
  228.     
  229.     def on_button_release_event(self, widget, event):
  230.         self.button_down = False
  231.         self.on_value_changed(self.vadjust[self.current_treeview_name])
  232.  
  233.     
  234.     def on_value_changed(self, adjustment):
  235.         '''Load more results when we get near the bottom of the treeview'''
  236.         if not (self.button_down) and (adjustment.get_value() + adjustment.page_size) / adjustment.upper > 0.8 and self.results[self.current_treeview_name] >= self.max_results:
  237.             if self.current_treeview_name == 'search':
  238.                 if self.debug:
  239.                     print 'Getting more results for search "' + self.search_terms + '" from offset ' + str(self.start_index['search'])
  240.                 
  241.                 self.get_results('/feeds/api/videos?vq=' + urllib.quote_plus(self.search_terms) + '&max-results=' + str(self.max_results) + '&orderby=relevance&start-index=' + str(self.start_index['search']), 'search', False)
  242.             elif self.current_treeview_name == 'related':
  243.                 if self.debug:
  244.                     print 'Getting more related videos for video "' + self.youtube_id + '" from offset ' + str(self.start_index['related'])
  245.                 
  246.                 self.get_results('/feeds/api/videos/' + urllib.quote_plus(self.youtube_id) + '/related?max-results=' + str(self.max_results) + '&start-index=' + str(self.start_index['related']), 'related', False)
  247.             
  248.         
  249.  
  250.     
  251.     def convert_url_to_id(self, url):
  252.         '''Find the last clause in the URL; after the last /'''
  253.         return url.split('/').pop()
  254.  
  255.     
  256.     def populate_list_from_results(self, search_token, treeview_name, thread):
  257.         '''Check to see if this search has been cancelled'''
  258.         if search_token != self.search_token[treeview_name]:
  259.             return False
  260.         if not thread.done:
  261.             if self.current_treeview_name == treeview_name:
  262.                 self.progress_bar.pulse()
  263.             
  264.             return True
  265.         CallbackThread(self.process_next_thumbnail, search_token, treeview_name).start()
  266.         return False
  267.  
  268.     
  269.     def process_next_thumbnail(self, search_token, treeview_name):
  270.         '''Note that all the calls to gobject.idle_add are so that the respective
  271. \t\t   UI function calls are made in the main thread, since process_next_thumbnail
  272. \t\t   is run in the CallbackThread thread.'''
  273.         if search_token != self.search_token[treeview_name]:
  274.             return False
  275.         if self.entry[treeview_name] == None or len(self.entry[treeview_name]) == 0:
  276.             gobject.idle_add(self._clear_ui, treeview_name)
  277.             self.entry[treeview_name] = None
  278.             self.in_search[treeview_name] = False
  279.             return False
  280.         entry = self.entry[treeview_name].pop(0)
  281.         self.results[treeview_name] += 1
  282.         self.start_index[treeview_name] += 1
  283.         youtube_id = self.convert_url_to_id(entry.id.text)
  284.         for _element in entry.extension_elements:
  285.             if _element.tag == 'group':
  286.                 break
  287.                 continue
  288.             len(self.entry[treeview_name]) == 0
  289.         
  290.         content_elements = _element.FindChildren('content')
  291.         if len(content_elements) == 0:
  292.             return True
  293.         mrl = content_elements[0].attributes['url']
  294.         thumbnail_url = _element.FindChildren('thumbnail')[0].attributes['url']
  295.         
  296.         try:
  297.             (filename, headers) = urllib.urlretrieve(thumbnail_url)
  298.         except IOError:
  299.             len(content_elements) == 0
  300.             len(content_elements) == 0
  301.             search_token != self.search_token[treeview_name]
  302.             return True
  303.  
  304.         
  305.         try:
  306.             pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
  307.         except gobject.GError:
  308.             len(content_elements) == 0
  309.             len(content_elements) == 0
  310.             search_token != self.search_token[treeview_name]
  311.             print 'Could not open thumbnail ' + filename + ' for video. It has been left in place for investigation.'
  312.             return True
  313.  
  314.         os.unlink(filename)
  315.         t_param = self.resolve_t_param(youtube_id)
  316.         gobject.idle_add(self._append_to_liststore, treeview_name, pixbuf, entry.title.text, mrl, youtube_id, search_token)
  317.         return True
  318.  
  319.     
  320.     def _clear_ui(self, treeview_name):
  321.         '''Revert the cursor'''
  322.         window = self.vbox.window
  323.         window.set_cursor(None)
  324.         if self.in_search == True or self.current_treeview_name == treeview_name:
  325.             self.progress_bar.set_fraction(0)
  326.             self.progress_bar.set_text('')
  327.         
  328.         return False
  329.  
  330.     
  331.     def _append_to_liststore(self, treeview_name, pixbuf, title, mrl, id, search_token):
  332.         '''Check to see if this search has been cancelled'''
  333.         if search_token != self.search_token[treeview_name]:
  334.             return False
  335.         if self.in_search == True or self.current_treeview_name == treeview_name:
  336.             self.progress_bar.set_fraction(float(self.results[treeview_name]) / float(self.max_results))
  337.         
  338.         self.liststore[treeview_name].append([
  339.             pixbuf,
  340.             title,
  341.             mrl,
  342.             id])
  343.         return False
  344.  
  345.     
  346.     def on_search_button_clicked(self, button):
  347.         search_terms = self.search_entry.get_text()
  348.         if self.debug:
  349.             print 'Searching for "' + search_terms + '"'
  350.         
  351.         self.notebook.set_current_page(self.notebook_pages.index('search'))
  352.         self.search_terms = search_terms
  353.         self.start_index['search'] = 1
  354.         self.results['search'] = 0
  355.         self.progress_bar.set_text(_('Fetching search results...'))
  356.         self.get_results('/feeds/api/videos?vq=' + urllib.quote_plus(search_terms) + '&orderby=relevance&max-results=' + str(self.max_results), 'search')
  357.  
  358.     
  359.     def on_search_entry_activated(self, entry):
  360.         self.search_button.clicked()
  361.  
  362.     
  363.     def get_results(self, url, treeview_name, clear = True):
  364.         if self.in_search[treeview_name] == True and clear == False:
  365.             if self.debug:
  366.                 print 'Cancelling getting more results due to existing incomplete search.'
  367.             
  368.             self.in_search[treeview_name] = False
  369.             return None
  370.         if clear == False:
  371.             self.results[self.current_treeview_name] = 0
  372.             self.progress_bar.set_text(_('Fetching more videos...'))
  373.         
  374.         if clear:
  375.             self.liststore[treeview_name].clear()
  376.         
  377.         if self.debug:
  378.             print 'Getting results from URL "' + url + '"'
  379.         
  380.         self.in_search[treeview_name] = True
  381.         self.search_token[treeview_name] = random.random()
  382.         window = self.vbox.window
  383.         window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  384.         if self.current_treeview_name == treeview_name:
  385.             self.progress_bar.pulse()
  386.         
  387.         thread = DownloadThread(self, url, treeview_name)
  388.         gobject.timeout_add(350, self.populate_list_from_results, self.search_token[treeview_name], treeview_name, thread)
  389.         thread.start()
  390.  
  391.  
  392.